//
//  File.swift
//  
//
//  Created by tgy on 2024/8/10.
//

import Foundation
import CLwIP
import NIO

class LWIPTunHub {
    
    let netif: UnsafeMutablePointer<netif>? = nil
    let tcpListenPcb: UnsafeMutablePointer<tcp_pcb>? = tcp_new_ip_type(u8_t(IPADDR_TYPE_ANY.rawValue))
    let udpPcb: UnsafeMutablePointer<udp_pcb>? = udp_new_ip_type(u8_t(IPADDR_TYPE_ANY.rawValue))
    
    let group: MultiThreadedEventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1)
    let eventLoop: EventLoop
    
    func getEventLoop() -> EventLoop {
        return eventLoop
    }
    
    func setMTU(mtu: UInt16) {
        netif?.pointee.mtu = mtu
    }
    
    // 初始化 lwIP 并设置回调函数
    init() {
        defer {
            do {
                try group.syncShutdownGracefully()
            } catch {
                print("Error shutting down event loop group: \(error)")
            }
        }
        eventLoop = group.next()
        // 初始化 lwIP
        lwip_init()
        
        // setup netif
        netif_add_noaddr(netif, nil, np_netif_init, ip_input)
        netif?.pointee.mtu = 1500  // set default mtu
        netif_set_up(netif)
        netif_set_link_up(netif)
        netif_set_default(netif)

        // setup tcp pcb
        var tcpListenPcb = tcp_new_ip_type(u8_t(IPADDR_TYPE_ANY.rawValue))
        if (tcpListenPcb != nil) {
            tcp_bind_netif(tcpListenPcb, netif)
            // 关闭拥塞控制
    //        tcp_nagle_disable(tcpListenPcb)
            if (tcp_bind(tcpListenPcb, nil, 0) == ERR_OK.rawValue) {
                tcpListenPcb = tcp_listen_with_backlog(tcpListenPcb, u8_t(TCP_DEFAULT_LISTEN_BACKLOG))
                // 设置回调函数
                tcp_accept(tcpListenPcb, np_tcp_accept_callback)
                tcp_recv(tcpListenPcb, np_tcp_recv_callback)
            } else {
              /* abort? output diagnostic? */
            }
        } else {
          /* abort? output diagnostic? */
        }
        // setup udp pcb
        let udpPcb = udp_new_ip_type(u8_t(IPADDR_TYPE_ANY.rawValue))
        if (udpPcb != nil) {
            udp_bind_netif(udpPcb, netif);
            udp_bind (udpPcb, nil, 0);
            udp_recv (udpPcb, np_udp_recv, nil);
        } else {
          /* abort? output diagnostic? */
        }
    }
    
    func input(data: NSData) -> err_t {
        var err = err_t(ERR_OK.rawValue)
        // 断言数据长度小于等于网络接口的 MTU
        assert(data.length <= (netif?.pointee.mtu)!, "error in data length or mtu value")
        
        // 分配 pbuf 并检查是否成功
        guard let p = pbuf_alloc(PBUF_RAW, UInt16(data.length), PBUF_RAM) else {
            fatalError("error in pbuf_alloc")
        }
        
        // 将数据复制到 pbuf 并检查是否成功
        let result = pbuf_take(p, data.bytes, UInt16(data.length))
        assert(result == ERR_OK.rawValue, "error in pbuf_take")
        
        // 加锁
        eventLoop.execute {
            // 判断 IP 版本并调用相应的输入函数
            if ipHdrGetVersion(p.pointee.payload) == 6 {
                err = ip6_input(p, self.netif)
            } else {
                err = ip4_input(p, self.netif)
            }
        }
        return err
    }
    
}
